package cn.com.jrr.core.dao.impl;

import java.io.Serializable;
import java.math.BigInteger;
import java.util.List;

import javax.transaction.Transactional;

import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.jboss.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate4.HibernateTemplate;
import org.springframework.orm.hibernate4.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;

import cn.com.jrr.core.dao.BaseDao;
import cn.com.jrr.core.model.DataTableRequest;
import cn.com.jrr.core.model.DataTableResponse;
import cn.com.jrr.core.model.PageModel;
import cn.com.jrr.core.model.TestModel;


@Repository
@SuppressWarnings("all")
public class BaseDaoImpl<T> extends HibernateTemplate implements BaseDao<T>{
	@Autowired
	private PageModel pageModel;
	@Autowired
	private SessionFactory sessionFactory;
	@Autowired
	private DataTableResponse<T> dataTableResponse;
	private Session session=null;
	private Logger logger=Logger.getLogger("logger");

	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}
	@Autowired
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}
	public Session getCurrentSession() {
		this.session=sessionFactory.openSession();
		return session;
	}
	public void closeSession() {
		if(session!=null){
			session.close();
		}
	}

	/*@Override
	public Serializable save(T o) {
		Serializable sb=this.getCurrentSession().save(o);
		closeSession();
		return sb;
	}

	@Override
	public void delete(T o) {
		this.getCurrentSession().delete(o);
		closeSession();
	}

	@Override
	public void update(T o) {
		this.getCurrentSession().update(o);
		closeSession();
	}

	@Override
	public void saveOrUpdate(T o) {
		this.getCurrentSession().saveOrUpdate(o);
		closeSession();
	}*/

	@Override
	public List<T> find(String hql, Object... params) {
		Query query=this.getCurrentSession().createQuery(hql);
		if (params != null) {
			int len = params.length;
			if (len > 0) {
				for (int i = 0; i < len; i++) {
					query.setParameter(i, params[i]);
				}
			}
		}
		count(hql,params);
		List<T> list=query.list();
		closeSession();
		return list;
	}

	@Override
	public List<T> find(String hql, int page, int rows,Object... params) {
		Query query = this.getCurrentSession().createQuery(hql);
		if (params != null) {
			int len = params.length;
			if (len > 0) {
				for (int i = 0; i < len; i++) {
					query.setParameter(i, params[i]);
				}
			}
		}

		List<T> list=query.setFirstResult((page - 1) * rows).setMaxResults(rows).list();
		closeSession();
		return list;
	}



	@Override
	public Long count(String hql,Object... params ) {
		int fromIndex = hql.indexOf("from");
		hql = "select count(*) " + hql.substring(fromIndex);
		logger.info("执行hql——>"+hql);
		Query query = this.getCurrentSession().createQuery(hql);
		if (params != null) {
			int len = params.length;
			if (len > 0) {
				for (int i = 0; i < len; i++) {
					query.setParameter(i, params[i]);
					logger.info("参数——>"+params[i]);
				}
			}
		}
		Long cc=((Long) query.uniqueResult());
		closeSession();
		return cc;
	}

	/*@Override
	public T get(Class<T> c, Serializable id) {
		Object o=this.getCurrentSession().get(c, id);
		closeSession();
		return (T) o;
	}*/



	@Override
	public T get(String hql, Object... params) {
		Query query=this.getCurrentSession().createQuery(hql);
		if (params != null) {
			int len = params.length;
			if (len > 0) {
				for (int i = 0; i < len; i++) {
					query.setParameter(i, params[i]);
				}
			}
		}
		List<T> list=query.list();
		closeSession();
		if(list.size()>0 && list!=null){
			return list.get(0);
		}
		return null;
	}

	@Override
	public DataTableResponse<T> find(String hql, PageModel<T> pageModel, Object... params) {
		logger.info("执行hql——>"+hql);
		Query query = this.getCurrentSession().createQuery(hql);
		if (params != null) {
			int len = params.length;
			if (len > 0) {
				for (int i = 0; i < len; i++) {
					query.setParameter(i, params[i]);
					logger.info("参数——>"+params[i]);
				}
			}
		}
		List<T> list=query.setFirstResult(pageModel.getCurrentItem()).setMaxResults(pageModel.getPageSize()).list();
		closeSession();
		dataTableResponse.setData(list);
		dataTableResponse.setRecordsTotal(count(hql,params).intValue());
		dataTableResponse.setRecordsFiltered(count(hql,params).intValue());
		dataTableResponse.setDraw(pageModel.getCurrentItem());
		return dataTableResponse;

	}
	@Transactional
	@Override
	public int updateBySql(String sql,Object... params) {
		SQLQuery query = this.getCurrentSession().createSQLQuery(sql);
		if (params != null) {
			int len = params.length;
			if (len > 0) {
				for (int i = 0; i < len; i++) {
					query.setParameter(i, params[i]);
					logger.info("参数——>"+params[i]);
				}
			}
		}
		int res=query.executeUpdate();
		closeSession();
		return res;
	}

	@Override
	public DataTableResponse<T> findBySql(String sql,PageModel<T> pageModel,Class<T> c,Object... params) {
		logger.info("执行sql——>"+sql);
		SQLQuery query = this.getCurrentSession().createSQLQuery(sql);
		if (params != null) {
			int len = params.length;
			if (len > 0) {
				for (int i = 0; i < len; i++) {
					query.setParameter(i, params[i]);
					logger.info("参数——>"+params[i]);
				}
			}
		}
		query.addEntity(c);
		List<T> list=query.setFirstResult(pageModel.getCurrentItem()).setMaxResults(pageModel.getPageSize()).list();
		closeSession();
		dataTableResponse.setData(list);
		int total=countBySql(sql,params);
		dataTableResponse.setRecordsTotal(total);
		dataTableResponse.setRecordsFiltered(total);
		dataTableResponse.setDraw(pageModel.getCurrentItem());
		return dataTableResponse;

	}

	@Override
	public int countBySql(String sql,Object... params) {
		int fromIndex = sql.indexOf("from");
		sql = "select count(*) " + sql.substring(fromIndex);
		Query query = this.getCurrentSession().createSQLQuery(sql);
		if (params != null) {
			int len = params.length;
			if (len > 0) {
				for (int i = 0; i < len; i++) {
					query.setParameter(i, params[i]);
				}
			}
		}
		int res=((BigInteger) query.uniqueResult()).intValue();
		closeSession();
		return res;
	}

	@Override
	public List<T> findBySql(String sql, Class<T> c, Object... params) {
		logger.info("执行sql——>"+sql);
		SQLQuery query = this.getCurrentSession().createSQLQuery(sql);
		if (params != null) {
			int len = params.length;
			if (len > 0) {
				for (int i = 0; i < len; i++) {
					query.setParameter(i, params[i]);
					logger.info("参数——>"+params[i]);
				}
			}
		}
		query.addEntity(c);
		List<T> list=query.list();
		closeSession();
		return list;
	}

	@Override
	public List<Object> findBySql(String sql, Object... params) {
		logger.info("执行sql——>"+sql);
		SQLQuery query = this.getCurrentSession().createSQLQuery(sql);
		if (params != null) {
			int len = params.length;
			if (len > 0) {
				for (int i = 0; i < len; i++) {
					query.setParameter(i, params[i]);
					logger.info("参数——>"+params[i]);
				}
			}
		}
		List<Object> list=query.list();
		closeSession();
		return list;
	}

	@Override
	public void updateByHql(T o) {
		this.getCurrentSession().update(o);
		this.getCurrentSession().flush();
		closeSession();
	}

	@Override
	public void addByHql(T o) {
		this.getCurrentSession().save(o);
		closeSession();
	}

	@Override
	public Session getDefaultSession() {
		this.session=sessionFactory.openSession();
		return session;
	}
	@Override
	public Serializable saveO(T o) {
		return this.save(o);
	}
	@Override
	public void deleteObj(T o) {
		this.delete(o);
	}
	@Override
	public void updateObj(T o) {
		this.update(o);
	}
	@Override
	public void saveOrUpdateObj(T o) {
		this.saveOrUpdate(o);;

	}
	@Override
	public T getObj(Class<T> c, Serializable id) {
		return this.get(c, id);
	}


}
